package com.zmn.plat.business.impl.orderconfig.orderstock.sp;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.plat.business.interfaces.orderconfig.orderstock.sp.SpConfigBService;
import com.zmn.plat.model.entity.orderconfig.orderstock.SubmitDutyDateVO;
import com.zmn.plat.model.entity.orderconfig.orderstock.sp.*;
import com.zmn.plat.services.interfaces.orderconfig.oderstock.sp.SpConfigCloseService;
import com.zmn.plat.services.interfaces.orderconfig.oderstock.sp.SpConfigService;

/**
 * 描述: 服务商库存配置基础接口类
 *
 * @author tanghongjun
 * @since 2020-03-17 10:29:08
 **/
@Service
public class SpConfigBServiceImpl implements SpConfigBService {

    /**
     * 无限量库存
     */
    public static final int DEFAULT_STOCK = -1;

    /**
     * 默认系数为1
     */
    public static final double DEFAULT_COEFFICIENT = 1d;

    @Autowired
    SpConfigService spConfigService;

    @Autowired
    SpConfigCloseService spConfigCloseService;

    @Override
    public List<SpConfigVO> listVOPageByQuery(SpConfigQuery query) {
        Integer count = spConfigService.countByQuery(query);
        query.setTotalCount(count);
        if (count > 0) {
            List<SpConfig> spConfigList = spConfigService.listPageByQuery(query);

            List<Integer> configIdList = spConfigList.stream().map(SpConfig::getConfigId).collect(Collectors.toList());

            List<SpConfigClose> spConfigCloseList = Collections.emptyList();

            if (CollectionUtil.isNotNullOrEmpty(configIdList)) {
                spConfigCloseList = spConfigCloseService.listByConfigIdList(configIdList);
            }

            Map<Integer, List<SpConfigClose>> map = spConfigCloseList.stream().collect(Collectors.groupingBy(SpConfigClose::getConfigId));
            List<SpConfigVO> items = new ArrayList<>();
            SpConfigVO spConfigVO;
            SpConfig spConfig;
            for (int i = 0; i < spConfigList.size(); i++) {
                spConfigVO = new SpConfigVO();
                spConfig = spConfigList.get(i);
                BeanUtils.copyProperties(spConfig, spConfigVO);
                spConfigVO.setSpConfigCloseList(map.get(spConfig.getConfigId()));
                spConfigVO.setColseDays(combinationColseDays(map.get(spConfig.getConfigId())));
                items.add(spConfigVO);
            }

            return items;
        }
        return Collections.emptyList();
    }

    private String combinationColseDays(List<SpConfigClose> spConfigCloseList) {
        if (spConfigCloseList == null) {
            return "-";
        }
        Long todayTimestamp = DateUtil.getTodayTimestampMillis();
        SpConfigClose spConfigClose;
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < spConfigCloseList.size(); i++) {
            spConfigClose = spConfigCloseList.get(i);
            if (Objects.nonNull(spConfigClose.getDay()) && spConfigClose.getDay().getTime() >= todayTimestamp && Objects.equals(spConfigClose.getStatus(), GlobalConsts.NO)) {
                sb.append(sdf.format(spConfigClose.getDay())).append(",");
            }
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        } else {
            return "-";
        }
        return sb.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchSet(List<SpConfig> list, String operator) {
        SpConfig spConfig = list.get(0);
        Integer spId = spConfig.getSpId();
        Integer cityId = spConfig.getCityId();
        SpConfigQuery query = new SpConfigQuery();
        query.setSpId(spId);
        query.setCityId(cityId);
        Map<String, SpConfig> spConfigMap = spConfigService.listByQuery(query).stream().collect(Collectors.toMap(item -> item.getServCategId().toString(), item -> item, (p, u) -> p));

        List<SpConfig> modifyList = Lists.newArrayList();
        list.forEach(item -> {
            if (item.getStock() == null) {
                item.setStock(DEFAULT_STOCK);
            }
            if (item.getCoefficient() == null) {
                item.setCoefficient(DEFAULT_COEFFICIENT);
            }
        });
        List<SpConfig> insertList = list.stream().filter(item -> {
            SpConfig exists = spConfigMap.get(item.getServCategId().toString());
            if (exists == null) {
                return true;
            }
            item.setConfigId(exists.getConfigId());
            modifyList.add(item);
            return false;
        }).peek(item -> {
            item.setStatus(GlobalConsts.YES);
            item.setCreater(operator);
            item.setCreateTime(DateUtil.getNow());
            item.setUpdater(operator);
            item.setUpdateTime(DateUtil.getNow());
        }).collect(Collectors.toList());

        if (insertList.size() > 0) {
            spConfigService.insertBatch(insertList);
        }

        if (modifyList.size() > 0) {
            for (SpConfig s : modifyList) {
                s.setUpdater(operator);
                s.setUpdateTime(DateUtil.getNow());
                spConfigService.updateByKey(s);
            }
        }

    }

    @Override
    public void closeDays(SubmitDutyDateVO<SpConfigCloseDayVO> vo) {
        List<Integer> configIds = vo.getData().getConfigIds();
        if (vo.getDays() != null && vo.getDays().size() > 0) {
            Map<Integer, List<SpConfigClose>> existsDayMap = spConfigCloseService.listByConfigIdList(configIds).stream().collect(Collectors.groupingBy(SpConfigClose::getConfigId));

            List<Integer> existsOpenIdList = Lists.newArrayList();
            List<SpConfigClose> insertList = configIds.stream().flatMap(configId -> vo.getDays().stream().map(day -> {
                SpConfigClose newClose = new SpConfigClose();
                newClose.setConfigId(configId);
                newClose.setDay(DateUtil.dateFormatToDate(day, DateUtil.FORMAT_DATE));
                newClose.setStatus(GlobalConsts.NO);
                newClose.setCreater(vo.getOperator());
                newClose.setCreateTime(DateUtil.getNow());
                newClose.setUpdater(vo.getOperator());
                newClose.setUpdateTime(DateUtil.getNow());
                return newClose;
            })).filter(item -> {
                List<SpConfigClose> closeList = existsDayMap.get(item.getConfigId());
                if (closeList == null || closeList.stream().noneMatch(day -> day.getDay().equals(item.getDay()))) {
                    // 没有找到则新增
                    return true;
                }
                // 存在开启则修改为关闭status=1
                Optional<Integer> existsOpenId = closeList.stream().filter(day -> day.getDay().equals(item.getDay()) && day.getStatus() == GlobalConsts.YES).map(SpConfigClose::getId).findFirst();
                existsOpenId.ifPresent(id -> existsOpenIdList.add(id));
                return false;
            }).collect(Collectors.toList());

            if (insertList.size() > 0) {
                spConfigCloseService.insertBatch(insertList);
            }
            if (existsOpenIdList.size() > 0) {
                for (Integer existsOpenId : existsOpenIdList) {
                    SpConfigClose modifyClose = new SpConfigClose();
                    modifyClose.setId(existsOpenId);
                    modifyClose.setStatus(GlobalConsts.NO);
                    modifyClose.setUpdater(vo.getOperator());
                    modifyClose.setUpdateTime(DateUtil.getNow());
                    spConfigCloseService.updateByKey(modifyClose);
                }
            }
        }

    }

    @Override
    public void openDays(List<Integer> ids, String operator) {
        for (Integer id : ids) {
            SpConfigClose open = new SpConfigClose();
            open.setId(id);
            open.setStatus(GlobalConsts.YES);
            spConfigCloseService.updateByKey(open);
        }
    }
}
